<?php
/*
 * xpager
 *
 * Refbook pagination
 *
 * @version:	0.1
 * @package:	radcore
 * @update:		30 jan 2011
 * @link:		http://radiance-project.com/
 * @link:		http://qfox.ru/
 * @author:		alex <alex@qfox.ru> yaroshevich
 * @copyright:	(c) 2008-2011 radiance framework
 */

class xpager {

    /**
     * @var integer number of items
     * @access protected
     */
    protected $total_items;

    /**
     * @var integer number of items per page
     * @access protected
     */
    protected $per_page = 10;

    /**
     * @var integer number of page links for each window
     * @access protected
     */
    protected $parallax = 4;

    /**
     * @var integer const number of page links at start - at least 2 first pages will be showed
     * @access protected
     */
    protected $at_start = 1;

    /**
     * @var integer const number of page links at end
     * @access protected
     */
    protected $at_end = 1;

    /**
     * @var integer current page number
     * @access protected
     */
    protected $current_page = null;

    /**
     * @var integer total pages number
     * @access protected
     */
    protected $total_pages = 1;

    /**
     * @var string path name
     * @access protected
     */
    protected $url_pattern = '?page=:page';

    /**
     * @var string specifies which param to use
     * @access protected
     */
    protected $request_var = 'get_page';

    /**
     * @var string pattern for anchor render
	 * @todo: use it in display
     * @access protected
     */
    protected $link_pattern = ':anchor ';

    /**
     * @var string pattern for selected page
	 * @todo: use it in display
     * @access protected
     */
    protected $selected_link_pattern = '<span></span>';

    /**
     * @var string name of the session var for number of items per page
	 * @todo: use it
     * @access protected
     */
    protected $session_per_page		= 'pager__items_per_page';

    /**
     * @var array Array with a key => value pair representing
     * @access protected
     */
    protected $pages = array();

    /**
     * @var array list of available options (safety check)
     * @access protected
     */
    protected $allowed_options = array(
		'pages',
        'total_items',
        'per_page',
		'at_start',
		'at_end',
        'parallax',
        'total_pages',
        'current_page',

        'url_pattern',
		'request_var',

        'session_per_page',
    );

	public function __construct()
	{
		$this->parse_current_page();
	}

	public function set_options($o)
	{
		if (!empty($o['total_items']) || !empty($o['total_pages']))
			$this->pages = array();

		foreach( $o as $k => $v )
		{
			if (!in_array($k,$this->allowed_options))
				continue;

			$this->$k = $v;
		}
	}

	public function build()
	{
        if (!empty($this->pages))
			$this->total_pages = count($this->pages);

		elseif (!empty($this->total_items)) {
			$this->total_pages = intval( ($this->total_items-1) / $this->per_page ) + 1;
			$l = range(1,$this->total_pages);
			$this->pages = array_combine( $l, $l );

		} else
			return false;

		$this->current_page = min($this->current_page, $this->total_pages);
		return true;
	}

	public function parse_current_page($from_request = false)
	{
		if (!is_null($this->current_page) && !$from_request)
			return;

		$page = reqi()->{$this->request_var};

		$this->current_page = max(1,(int)($page));
	}

	public function get_current_page()
	{
		if ($this->disabled())
			return 1;

		return $this->current_page;
	}

	public function get_total_pages()
	{
		if ($this->disabled())
			return 1;

		return $this->total_pages;
	}

	public function get_limit()
	{
		if ($this->disabled())
			return null;

		$this->parse_current_page(true);

		$quantity = $this->per_page;
		$from = $quantity * ($this->current_page-1);

		if ($from > $this->total_items)
		{
			// ?
		}

		return array( $from, $quantity );
	}

	public function render_page_url( $p )
	{
		return subst( $this->url_pattern, array( 'page' => (int)($p) ) );
	}

	public function display()
	{
		if ($this->disabled())
			return '';

		//if (!$this->per_page) $this->per_page = $this->total_items;
		/*{if !$quantity}{assign var=quantity value=$list|@sizeof}{/if}
		{if !$ends}{assign var=ends value=1}{/if}
		{if !$url_template}{assign var=url_template value="/page@p/"}{/if}
		{if !$parallax}{assign var=parallax value=4}{/if}*/

		if ($this->total_pages < 2)
			return '';

		$total_pages	= $this->total_pages;
		$current_page	= $this->current_page;
		$pages			= $this->pages;
		$parallax		= $this->parallax;
		$url_pattern	= $this->url_pattern;
		$at_start		= $this->at_start;
		$at_end			= $this->at_end;

		$r = '';

		/* lprlx: current-leftparallax > atend_quantity+1, because first&second links will be printed */
		$lprlx = max( $current_page - $parallax - 1, 1 );
		if ($lprlx <= $at_start + 1)
			$lprlx = 1;

		/* rprlx: rightparallax < list_quantity-atends_quantity-1, because last&prelast links also will be printed */
		$rprlx = min( $current_page + $parallax + 1, $total_pages );
		if ($rprlx >= $total_pages - $at_end)
			$rprlx = $total_pages;

		/*<div class="debug">quantity:{$quantity}, l:{$lprlx}, r:{$rprlx}</div>*/
	
		$r .= '<span class="leftonly">Страницы:</span>';
		if ( $total_pages > 2 ) {
			$r .= '<span class="leftright">';
			$r .= ($current_page>1)
				? '&larr;&nbsp;<a href="' . $this->render_page_url($current_page-1) . '">назад</a>'
				: '<span class="inactive">&larr; назад</span>';
			$r .= '&nbsp;';
			$r .= ($current_page < $total_pages)
				? '<a href="' . $this->render_page_url($current_page+1) . '">вперед</a>&nbsp;&rarr;'
				: '<span class="inactive">вперед &rarr;</span>';
			$r .= '</span>';
		}

		$out = '';
		$leftdots = $rightdots = 0;

		foreach ($pages as $k => $text) {
			if ($k == $current_page) {
				$out .= '<span class="selected">' . $text . '</span>';
			} else {
				if ( ($lprlx < $k && $k < $current_page) || ($current_page < $k && $k < $rprlx) || ($k <= $at_start) || ($total_pages - $at_end < $k) ) {
					$out .= '<span class="prlx' . abs($current_page - $k) . '"><a href="' . $this->render_page_url($k) . '">' . $k . '</a></span>';

				} elseif ( !$leftdots && $k < $current_page ) {
					$leftdots = true;
					$out .= '<a href="' . $this->render_page_url($lprlx/2 + 1) . '">...</a>';

				} elseif ( !$rightdots && $current_page < $k ) {
					$rightdots = true;
					$out .= '<a href="' . $this->render_page_url($rprlx/2 + $total_pages/2) . '">...</a>';
				}
			}
		}

		/*{if $n != $current_page}
			{if ( $lprlx < $n and $n < $current_page)
			 or ( $current_page < $n and $n < $rprlx)
			 or ( $n <= $ends ) or ( $total_pages-$ends < $n )}
				$listing_out = '<span class="prlx{$current_page-$n|abs}"><a href="{$url_pattern|replace:'@p':$n}">{$n}</a></span>';
			{elseif ( !$leftdots and $n < $current_page)}
				{assign var=leftdots value=1}
				<a href="{assign var=n value=$lprlx/2+1|@intval}{$url_pattern|replace:'@p':$n}">...</a>
			{elseif ( !$rightdots and $current_page < $n)}
				{assign var=rightdots value=1}
				<a href="{assign var=n value=$rprlx/2+$total_pages/2|@intval}{$url_pattern|replace:'@p':$n}">...</a>
			{/if}
		{else}<span class="selected">{$n}</span>{/if}
		{/foreach}*/

		$r .= '<div class="listing">' . $out . '</div>';
		$r .= '<div class="clear"></div>';

		return $r;
	}



	protected $disabled = false;

	public function disable(){
		$this->disabled = true;
	}

	public function enable(){
		$this->disabled = false;
	}

	public function disabled(){
		return $this->disabled;
	}

	public function enabled(){
		return !$this->disabled;
	}
}
